/***************************************************************************
 *   Copyright (C) 2008 by Łukasz Spintzyk   *
 *   lukasz.spintzyk@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "display.h"
#include <stdlib.h>
#include <string.h>

uint8_t screen_memorych1[DDATA_AREA_SIZE_W/FONT_SIZE+1];
uint8_t screen_memorych2[DDATA_AREA_SIZE_W/FONT_SIZE+1];


/*! Function draws grid 
 * TDIV_W * UDIV_H
 */
void drawGrid(uint16_t baseaddres){
    uint8_t x=0,y=0;
    uint16_t address=0;

    for (y=0;y<DDATA_AREA_SIZE_H;y+=UDIV_H){
        for (x=0;x<DDATA_AREA_SIZE_W;x+=TDIV_W){
            address=y;
            address*=40;
            address+=x/6 + baseaddres;
            lcd_write_2cmd((uint8_t)address,(uint8_t)(address>>8), SETADDRESSPTR);
            lcd_write_0cmd(NBITSET|(5-x%6));

        }
    }
}

void drawCursors(){
    static uint8_t x1=0,x2=0,y1=0,y2=0;
    uint8_t x,y,px=0;

    if ((y1/8)!=(cursor1.y/8)){
        y=y1/8;
        for (x=0;x<29;x+=2)
            display_char(' '-0x20,x,y);
        y1=cursor1.y;
    }
    
    if ((y2/8)!=(cursor2.y/8)){
        y=y2/8;
        for (x=1;x<29;x+=2)
            display_char(' '-0x20,x,y);
        y2=cursor2.y;
    }
    
    y=cursor1.y/8 ;
    px=7-cursor1.y%8;
    for(x=0;x<29;x+=2)
        display_char(0x86+px,x,y);
    
  
    y=cursor2.y/8;
    px=7-cursor2.y%8;
    for(x=1;x<29;x+=2)
        display_char(0x86+px,x,y);
    
    
    if (x1!=cursor1.x){
        x=x1/FONT_SIZE;
        px=x1%6;
        for (y=1;y<8;y+=2)
            display_char(' '-0x20,x,y);
        x1=cursor1.x;
    }
    
    if (x2!=cursor2.x){
        x=x2/FONT_SIZE;
        px=x2%6;
        for (y=0;y<8;y+=2)
            display_char(' '-0x20,x,y);
        x2=cursor2.x;
    }
    
    x=cursor1.x/FONT_SIZE;
    px=5-cursor1.x%6;
    for (y=1;y<8;y+=2)
        display_char(0x80+px,x,y);
    
    x=cursor2.x/FONT_SIZE;
    px=5-cursor2.x%6;
    for (y=0;y<8;y+=2)
        display_char(0x80+px,x,y);
}


void drawChannels(){
    //first will be drawn channel1
    uint16_t adress;
    uint8_t x=0;
    cli();
    for (x=0;x<DDATA_AREA_SIZE_W;x++){
        adress=(x/FONT_SIZE)*40 + screen_memorych1[x];
        screen_memorych1[x]=0;
        lcd_write_2cmd((uint8_t)adress,(uint8_t)(adress>>8), SETADDRESSPTR);
        lcd_write_0cmd(NBITSET|(x%6));
    }
    sei();

}

void sendToDisplay(int8_t value){
        //! \todo chyba przenios� t� funkcj� do przerwania, tam na�o�y si� wszystkie kana�y.
 //   if ((value<0) && (value>63)) value-=63;
 //   uint8_t x=getTime();
 //   if ((lcd_x!=x) || (lcd_y!=value/8-1))
 //       lcdGoTo(lcd_x,value/8-1);//wybierz stron�
        //! \todo doda� mask� siatki
  //  lcdWriteData((1 << (value % 8)));
}

/*! Function which parse integer value to string, max value 9999
 * \param where point where to print value
 * \param val -value to print
 * \param unit string with 2characters of unit value 
 */ 
void displayValue(upoint8_t where, int16_t val,char * unit){
    
    char liczba[10]={' '};
    
    itoa(val,liczba,10);
    strcat(liczba,unit);
    
    display_text(liczba,where.x,where.y);

}

void displayRadixValue(upoint8_t where, int16_t val, uint8_t radix){
    char liczba[20];
    itoa(val,liczba,radix);
    display_text(liczba,where.x,where.y);
    
}

/*! Function draws oscilloscope menu.
 */
void drawInfo(){
    
    //Write "V/div=" on DINFOXO
    display_text_PGM(PSTR("V/div="),VOLTPERDIV_X,VOLTPERDIV_Y);
    
    //Write V value and unit
    setVoltDiv(0,false);
    
    //Write t/div=
    display_text_PGM(PSTR("t/div="),TIMEPERDIV_X,TIMEPERDIV_Y);
    
    //Write time unit and value
    setTimeDiv(0,false);
    
    //Write U=
    display_text_PGM(PSTR("U="),VOLTCURSOR_X,VOLTCURSOR_Y);
    
    
    
    
    //Write T=
    display_text_PGM(PSTR("T="),TIMECURSOR_X,TIMECURSOR_Y);
    
    //Write Cursor T unit and value
    //Write Cursor V unit and value
    setCursor(0,false);
    
    
    //Write X1 Y1 X2 Y2 which means cursors
    display_text_PGM(PSTR("X1 Y1 X2 Y2"),CURSORX1_X,CURSOR_Y);
    
    
    if ((DEV_state & (1<<ISCH1)) && (!(DEV_state & (1<<ISHV))))
        display_text_PGM(PSTR("CH1"),CH1_X,CH1_Y);
    else if ((DEV_state & (1<<ISHV)) && ((DEV_state & (1<<ISCH1))))
        display_text_PGM(PSTR("CH1-HV"),CH1_X,CH1_Y);
    else display_text_PGM(PSTR(" * "),CH1_X,CH1_Y);


    if ((DEV_state & (1<<ISCH2)) &&(!(DEV_state & (1<<ISTB)) ))
        display_text_PGM(PSTR("CH2"),CH2_X,CH2_Y);
    else if ((DEV_state & (1<<ISTB))  &&(!(DEV_state & (1<<ISCH2))))
        display_text_PGM(PSTR("TB "),CH2_X,CH2_Y);
    else if (!(DEV_state & (1<<ISTB)) && (!(DEV_state & (1<<ISCH2))))
        display_text_PGM(PSTR(" * "),CH2_X,CH2_Y);
    
    if ( (DEV_state & (1<<ISCH2)) && (DEV_state & (1<<ISTB)) )
        display_text_PGM((DEV_state & (1<<ISAC)) ? PSTR("AC") : PSTR("DC"),AC_X,AC_Y);
    else display_text_PGM(PSTR(" * "),AC_X,AC_Y);

    if (DEV_state & (1<<ISADD))
        display_text_PGM(PSTR("ADD "),ADD_X,ADD_Y);
    else 
        display_text_PGM(PSTR(" *  "),ADD_X,ADD_Y);
    
    if (DEV_state & (1<<ISSUB))
        display_text_PGM(PSTR("SUB "),SUB_X,SUB_Y);
    else 
        display_text_PGM(PSTR(" *  "),SUB_X,SUB_Y);
    
    display_text_PGM(PSTR("Fr"),FR_X,FR_Y);

}

/*! Function uses builit in  lcd_drive cursor.
 * \param visible set visibility of cursor
 * \param n_lines height of cursor form 1 to 8 pixels
 * \param blink sets blinking of cursor
 * \param x number of column
 * \param y number of row
 */
void showTextCursor(bool visible, uint8_t n_lines, bool blink, uint8_t x, uint8_t y){
    if (!visible){
        lcd_write_0cmd(SETDISPLAYMODE | TEXTONGRAPHICON);// this will disable cursor
        return;
    }
    
    //setCursor position
    lcd_write_2cmd(x,y,SETCURSORPTR);
    
    if (blink) 
        lcd_write_0cmd(SETDISPLAYMODE | TEXTONGRAPHICON | CURSORBLINKON);
    else
        lcd_write_0cmd(SETDISPLAYMODE | TEXTONGRAPHICON | CURSORBLINKOFF);
    
    lcd_write_0cmd(SET_N_LINECURSOR + n_lines);
}



//! --------------------- \deprecated Functuions below are deprecated

/*! Draws information text SET, that informes that user pressed setButton.
 * \deprecated Because I will use blinking Cursor which is build into lcd drive
 * \param if true then SET is drawn, else erased
 */
/*
void drawSET(bool draw)
{
    upoint8_t temp={lcd_x,lcd_y};
//asm ("PUSH lcd_x");
//asm ("PUSH lcd_y");

    lcdGoTo(SET_X1,SET_Y1);
    if (draw)lcdWriteChar2('S',false);
    else lcdWriteChar2(' ',false);

    lcd_y+=8;
    lcdGoTo(SET_X1,lcd_y);
    if (draw)lcdWriteChar2('E',false);
    else lcdWriteChar2(' ',false);

    lcd_y+=8;
    lcdGoTo(SET_X1,lcd_y);
    if (draw)lcdWriteChar2('T',false);
    else lcdWriteChar2(' ',false);


    lcd_x=temp.x;
    lcd_y=temp.y;
//asm ("POP lcd_x");
//asm ("POP lcd_y");
    lcdGoTo(lcd_x,lcd_y);
}
*/

/*! Function draw line on display
 * \param begin - starting point of line
 * \param end -ending point of line
 * \param off - if true line from begin to end schould be erased
 * Function draws only horizontal lines
 */
/*
void drawLine(upoint8_t begin, upoint8_t end, bool off)
{

    static upoint8_t last1={0,0};
    static upoint8_t last2={0,0};

    upoint8_t temp_pop={lcd_x,lcd_y};
//asm ("PUSH lcd_x");
//asm ("PUSH lcd_y");
    uint8_t i;
    if (last1.x-last2.x!=0)//je�li tak to zamaluj dawn� lini�
        for (i=last1.x; i<=last2.x; i++)
            lcdClrPixel(i, last1.y);



    if (!off) {
        for (i=begin.x; i<=end.x; i++)
            lcdSetPixel(i, begin.y);
        last1=begin;
        last2=end;
    } else {     //je�li nie ma by� malowana linia.
        last1.x=0;
        last2.x=0;
    }

    lcd_x=temp_pop.x;
    lcd_y=temp_pop.y;
//! \todo Sprawdzi� jak to si� kompiluje
//asm ("POP lcd_x");
//asm ("POP lcd_y");
    lcdGoTo(lcd_x,lcd_y);
}
*/

//! Funkcja korzysta z api lcdcontrol.h, wypisuje znaki na ekranie z tabicy znak�w znaki[]
/*
void lcdWriteChar2(char a, bool neg)
{
    char x=0;
    char len=3;
    switch (a) {
        case 'A':
            x=APOS;
            break;
        case 'B':
            x=BPOS;
            break;
        case 'C':
            x=CPOS;
            break;
        case 'D':
            x=DPOS;
            break;
        case 'E':
            x=EPOS;
            break;
        case 'F':
            x=FPOS;
            break;
        case 'H':
            x=HPOS;
            break;
        case 'r':
            x=rPOS;
            break;
        case 'S':
            x=SPOS;
            break;
        case 'T':
            x=TPOS;
            break;
        case 'U':
            x=UPOS;
            break;
        case 'u':
            x=uPOS;
            break;
        case 'V':
            x=VPOS;
            break;
        case 'X':
            x=XPOS;
            break;
        case 'Y':
            x=YPOS;
            break;
        case '*':
            x=GW_POS;
            break;
        case 'm':
            x=MPOS;
            len=MLEN;
            break;
        case '\\':
            x=DIVPOS;
            len=DIVLEN;
            break;
        case '=':
            x=EQPOS;
            len=EQLEN;
            break;
        case '.':
            x=ZERO_POS;
            len=ZERO_LEN;
            break;
        case ' ':
            x=SPACEPOS;
            len=SPACELEN;
            break;
        case '-':
            x=_POS;
            len=_LEN;
            break;
        default:
            if (a>='0' && a<='9') x=a-'0';
            break;
    };
    int i;
    for (i = 0; i < len; i++) // pi�ciokrotne wykonanie p�tli
        if (neg) {
        lcdWriteData(~pgm_read_byte(znaki + (len * x) + i)); // zapis sk�adowej znaku
        lcdWriteData(0xFF);
        } else {
            lcdWriteData(pgm_read_byte(znaki + (len * x) + i));
            lcdWriteData(0x00); // odst�p mi�dzy znakami
        }
}
*/
//! Funkcja korzysta z funkcji lcdWriteChar2(char,neg); Wypisuje string kt�ry znajduje sie w pami�ci programu
/*
void lcdWriteStringPGM2(char *str,bool neg)
{
    char c;
    while ((c = pgm_read_byte(str++)))  lcdWriteChar2(c, neg);
}
*/
//! Funkcja korzysta z funkcji lcdWriteChar2(char,neg); Wypisuje string kt�ry znajduje sie w pami�ci danych
/*
void lcdWriteString2(char *str,bool neg)
{
    char c;
    while ((c = *str++))  lcdWriteChar2(c, neg);
}
*/

